home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1453.dms / var1453.adf / Messages / Messages.doc < prev    next >
Text File  |  1992-05-03  |  28KB  |  904 lines

  1. 4    MESSAGES
  2.  
  3. 4.1  INTRODUCTION
  4.  
  5. The Amiga is a multi tasking machine, and thus there may be
  6. several programs running at the same time. Although each task
  7. is a separate process they can communicate with each other with
  8. help of Exec. When a program (task) want to communicate with
  9. another program, it creates a "message" that is posted at the
  10. other program's "message port". When the other program has read
  11. the message it can change it and "reply". The first program
  12. will then receive the new message.
  13.  
  14. To be able to communicate with other tasks running at the same
  15. time can be extremely useful. When you are using parts of the
  16. operating system it is also sometimes necessary to use message.
  17. The operating system will for example sometimes send you a
  18. message when it has completed your request, or it may be want
  19. to inform you about something.
  20.  
  21.  
  22.  
  23. 4.2  EXEC'S MESSAGE SYSTEM
  24.  
  25. A message is actually simply a structure containing some
  26. information Exec needs to handle the message, and your data
  27. you want to send. To send the message you then simply give the
  28. other program's message port a pointer to your structure. The
  29. message is not copied, you simply allow the other program to
  30. use some part of your own code.
  31.  
  32. It is important to remember that after you have sent a message
  33. the other program may read and alter it. You are therefore not
  34. allowed to use the message structure until the other program
  35. has replied. After the other program has replied you may of
  36. course do whatever you want with the structure. Note that the
  37. other program may have changed the message.
  38.  
  39. Before your program terminates you must have received a reply
  40. for every message you have sent! If there exist a message you
  41. have not received any reply for and your program terminates,
  42. the message structure is deallocated, and if the other program
  43. tries now to change the message..., a disaster may occur!
  44.  
  45.  
  46.  
  47. 4.2.1  MESSAGES
  48.  
  49. The message you want to send consist of two parts. The first
  50. part is the Message structure which is used by Exec to monitor
  51. all messages. The other part is the message itself. The whole
  52. message should be allocated as PUBLIC memory since several (at
  53. least two) tasks is using it. It must also be initialized
  54. before it is dispatched.
  55.  
  56. As said above, the first part of the message must contain a
  57. Message structure, which look like this: (defined in header
  58. file "exec/ports.h")
  59.  
  60. struct Message
  61. {
  62.   struct Node mn_Node;
  63.   struct *MsgPort *mn_ReplyPort;
  64.   UWORD mn_Length;
  65. };
  66.  
  67.  
  68. mn_Node:      A Node structure used to link the message to
  69.               the message port. (See previous chapter for more
  70.               information about lists.) The "ln_Type" field of
  71.               the Node structure should be set to "NT_MESSAGE".
  72.  
  73. mn_ReplyPort: Pointer to a message port to which the other
  74.               task's reply will be sent to. (After you have
  75.               sent a message you must receive a reply at this
  76.               port before you may deallocate the message's
  77.               memory.)
  78.  
  79. mn_Length:    The total length of the whole message.
  80.  
  81.  
  82. The other part is the message itself that you want to send. It
  83. may be anything from 0 up to almost 64KB long. So if you want
  84. to send a message containing some information about a person,
  85. the complete message structure should look something like this:
  86.  
  87.   struct MyMessage
  88.   {
  89.     struct Message System_msg; /* Used be Exec.         */
  90.     float height;              /* The message itself... */
  91.     float weight;
  92.     int age;
  93.     char name[ 20 ];
  94.   };
  95.  
  96.  
  97. The memory containing the message must be made "public", which
  98. means that more than one task may read and alter it. The
  99. easiest way to make it public is to allocate the memory with
  100. help of the function AllocMem(). Set the parameter MEMF_PUBLIC
  101. to make it public and MEMF_CLEAR to set all memory to 0.
  102.  
  103.   /* Declare a pointer to your message: */
  104.   struct MyMessage *msg;
  105.  
  106.   /* Allocate enough memory for the message: */
  107.   /* ("Clear the memory and make it public") */
  108.   msg = (struct MyMessage *)
  109.     AllocMem( sizeof( struct MyMessage  ), MEMF_PUBLIC | CLEAR );
  110.  
  111.  
  112.  
  113. 4.2.2  PREPARE MESSAGES
  114.  
  115. Before you may send the message you have to initialize some
  116. parts of the message:
  117.  
  118.   1. You must set the "ln_Type" field of the Node structure
  119.      to NT_MESSAGE. For example:
  120.  
  121.      /* It is a message: */ 
  122.      msg->System_msg.mn_Node.ln_Type = NT_MESSAGE;
  123.  
  124.   2. You need to specify which port the other program should
  125.      send the reply to when it has read the message. (It is
  126.      first when you receive a reply you may deallocate the
  127.      message's memory.) For example: ("replyport" is a pointer
  128.      to a MsgPort structure.)
  129.  
  130.      /*  Send replies to this port: */
  131.      msg->System_msg.mn_ReplyPort = replyport;
  132.  
  133.   3. You also have to tell the system how long your message
  134.      is. You do it by setting the "mn_Length" field to
  135.      sizeof( the whole message ). For example:
  136.      
  137.      /* Set size: */
  138.      msg->System_msg.mn_Length = sizeof( struct MyMessage );
  139.  
  140.   4. Finally you may set your own message, before you send it.
  141.      (If you are only interested in what the other program
  142.      will reply, you do not need to set any personal message.)
  143.      For example:
  144.      
  145.      msg->height = 190.5;
  146.      msg->weight = 75.0;
  147.      msg->age = 22;
  148.      strcpy( msg->name, "Anders Bjerin" );
  149.  
  150.  
  151.  
  152. 4.2.3  MESSAGE PORTS
  153.  
  154. Messages are sent to message ports where they are collected
  155. by the other task. A message port is actually a MsgPort
  156. structure that has been initialized in a special manner. The
  157. MsgPort structure look like this: (define in the header file
  158. "exec/ports.h")
  159.  
  160. struct MsgPort
  161. {
  162.   struct Node mp_Node;
  163.   UBYTE mp_Flags;
  164.   UBYTE mp_SigBit;
  165.   struct Task *mp_SigTask;
  166.   struct List mp_MsgList;
  167. };
  168.  
  169. mp_Node:    Used by the system. This Node structure contains
  170.             among many things the name of this message port.
  171.             (Each port should have a name if you want other
  172.             tasks to send messages to it.) The priority and
  173.             type (NT_MSGPORT) is also stored in this field.
  174.  
  175. mp_Flags:   This filed contains flags that tells the system
  176.             what it should do when a new message arrives. To
  177.             check which flag is set you first have to "mask"
  178.             the number with help of PF_ACTION before you
  179.             examine the "mp_Flags" field. Following flags
  180.             exist for the moment:
  181.             
  182.               PA_SIGNAL:  Each time a message arrives a signal
  183.                           will occur. (Even if there are
  184.                           several messages queued before this
  185.                           one, a signal will be broadcasted.
  186.                           See below for more information about
  187.                           signals.) 
  188.  
  189.               PA_SOFTINT: Each time a message arrives a
  190.                           software interrupt will occur.
  191.  
  192.               PA_IGNORE:  When a message will arrive nothing
  193.                           will happen.
  194.  
  195.             To check which flag is set, do like this: ("mp" is
  196.             a pointer to an initialized message port.)
  197.             if( mp->mp_Flags & PF_ACTION == PA_SIGNAL )
  198.               printf( "The PA_SIGNAL flag is set!\n" );
  199.             and so on...
  200.  
  201. mp_SigBit:  If this port has the PA_SIGNAL flag set, this bit
  202.             number will be "signaled".
  203.  
  204. mp_SigTask: Pointer to the task that should be signaled when
  205.             a message arrives. (Most of the time it is the same
  206.             task that created the port that should be signaled.)
  207.  
  208. mp_MsgList: Pointer to the list header in which all messages
  209.             will be stored.
  210.  
  211.  
  212.  
  213. 4.2.4  PREPARE MESSAGE PORTS
  214.  
  215. Luckily we do not have to initialize the MsgPort structure
  216. ourself if we do not want to. We only have to call the function
  217. CreatePort() and it will do everything for us.
  218.  
  219. CreatePort() allocates and initializes a MsgPort structure. If
  220. you give it a string as first parameter it will also make the
  221. port public. (A port that has a name can be found by other tasks
  222. and is therefore "public".) If CreatePort() of some reason could
  223. not create a message port it returns NULL, otherwise if
  224. everything is OK it returns a pointer to the new MsgPort
  225. structure.
  226.  
  227.   Synopsis: msgp = CreatePort( name, pri );
  228.   
  229.   msgp:     (struct MsgPort *) Pointer to the new MsgPort
  230.             structure, or NULL if something went wrong.
  231.  
  232.   name:     (char *) Pointer to a string containing the name
  233.             of the message port, or NULL. If it is a string
  234.             the port will be made public (so other tasks can
  235.             find it) else only our task can use it.
  236.   
  237.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure
  238.             that should be allocated.
  239.  
  240.   pri:      (BYTE) This message port's priority. Usually set
  241.             to 0 - normal priority.
  242.  
  243.  
  244. When your program terminates you must close the message port
  245. by calling the DeletePort() function!
  246.  
  247.   Synopsis: DeletePort( msgp );
  248.  
  249.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure,
  250.             that should be deallocated.
  251.  
  252.  
  253. Here is an example of how to create and delete a message port:
  254.  
  255.   /* Declare a pointer to our message port: */
  256.   struct MsgPort  *mp;
  257.  
  258.   /* Create the message port:            */
  259.   /* (Make the port public, priority 0.) */
  260.   mp = CreatePort( "ACM postbox", 0 );
  261.  
  262.   /* Check if we have received a message port or not: */
  263.   if( !mp )
  264.     /* ERROR! Could not create message port! */
  265.  
  266.   ...
  267.  
  268.   /* Close message port: */
  269.   DeletePort( mp );
  270.  
  271.  
  272.  
  273. 4.2.5  FIND OTHER TASK'S MESSAGE PORTS
  274.  
  275. If a program want to communicate with another program, it has
  276. to find the other task's message port. To do this it must know
  277. the name of that port and can then call the function FindPort()
  278. which will return a pointer to it.
  279.  
  280.   Synopsis: msgp = FindPort( name );
  281.   
  282.   msgp:     (struct MsgPort *) FindPort() will return a pointer
  283.             to the port we asked for, or NULL if it could not
  284.             find it.
  285.  
  286.   name:     (char *) Pointer to a string containing the name of
  287.             the port we are looking for.
  288.  
  289.  
  290. If we want to send a message to the "ACM postbox" port which
  291. we created above, do like this:
  292.  
  293.   /* Declare a pointer to the port we want to find: */
  294.   struct  MsgPort *acm_msgport;
  295.  
  296.   /* Try to find port "ACM postbox": */
  297.   acm_msgp = FindPort( "ACM postbox" );
  298.   
  299.   /* Have we found the port or not? */
  300.   if( !acm_msgp )
  301.     printf( "Could not find the message port!\n" );
  302.  
  303.  
  304.  
  305. 4.2.6  SEND MESSAGES
  306.  
  307. Once you have found some other programs message port and you
  308. have initialized a message you can send it by calling the
  309. function PutMsg(). It will put your message at the end of
  310. his queue of messages, and if the PA_SIGNAL flag was set
  311. in his MsgPort structure, he will also receive a signal.
  312.  
  313.   Synopsis: PutMsg( msgp, message );
  314.  
  315.   msgp:     (struct MsgPort *) Pointer to the message port
  316.             to which you want to send a message.
  317.  
  318.   message:  (struct Message *) Pointer to the whole message
  319.             area.
  320.  
  321.  
  322. For example: (We send our message declared above to our message
  323. port "ACM postbox" which we have just found.)
  324.  
  325.   /* Send our message: */
  326.   PutMsg( acm_msgp, msg );
  327.  
  328.  
  329.  
  330.  
  331. 4.2.7  WAITING FOR MESSAGES TO ARRIVE
  332.  
  333. When you are waiting for a message to arrive and you do not
  334. want to do anything else, you should put your task to sleep.
  335. A sleeping task does not use any computer-time, which means that
  336. other tasks which are maybe running will be executed faster.
  337.  
  338. There exist two ways of waiting for a message to arrive at a
  339. port. The simplest way is to call the function WaitPort() which
  340. will put the task to sleep until a message arrives.
  341.  
  342.   Synopsis: msg = WaitPort( msgp );
  343.   
  344.   msg:      (struct Message *) When a message arrives the task
  345.             is woken up and WaitPort() returns a pointer to the
  346.             first message that has arrived. (There may arrive
  347.             several messages at the same time.)
  348.  
  349.   msgp:     (struct MsgPort *) Pointer to the message port you
  350.             want to wait at.
  351.  
  352.  
  353. The disadvantage with the WaitPort() function is that you can
  354. only wait for messages to be received at one port. If you want
  355. to monitor several ports you have to use the function Wait().
  356.  
  357. If the message port's PA_SIGNAL flag was set we will receive a
  358. "signal" each time a message is put into our queue of received
  359. messages. But what is a signal actually? It is about time to
  360. explain it. However, if you are already confused you do not
  361. have to understand this. Simply do as in the examples, and it
  362. will work perfect.
  363.  
  364. Each time something happens, like a message arrives, the task
  365. also receives a signal. Each task may monitor up to 32
  366. different signals. The good thing about these signals is
  367. that you can tell the operating system (Exec) that you want to
  368. wait until something happens, and while you are waiting the
  369. task is put to sleep.
  370.  
  371. You specify what conditions should wake up the task, by telling
  372. Exec which signals should be received before the task should
  373. be forced to work again. If you want to wait until a message
  374. is received at the message port "msgp", you should give Exec
  375. that port's signal number. (Each port is assigned a signal
  376. number when they are created.) The field "msgp->mp_SigBit"
  377. contains the message port's signal number.
  378.  
  379. Use the function Wait() to put a task to sleep if you want to
  380. monitor several message ports.
  381.  
  382.   Synopsis: rsig = Wait( wsig )
  383.  
  384.   rsig:     (ULONG) When one of the specified signal bits was
  385.             received, the task is woken up and Wait() returns
  386.             the signal bit value that woke it up.
  387.  
  388.   wsig:     (ULONG) Wait() will put the task to sleep, and it
  389.             will only wake up if one of the specified signal
  390.             bit values is received.
  391.  
  392.  
  393. Here is an example that may make it a bit more understandable:
  394. (We want to monitor three message ports which we have already
  395. found, and they are: mp_meny, mp_gadget, mp_timer.)
  396.  
  397. ULONG meny_sig, gadget_sig, timer_sig, received_sig;
  398.  
  399. /* Get the ports signal values and transform it into bit */
  400. /* fields. Example:                                      */
  401. /* Signal value -> Bit field                             */
  402. /* ------------------------------------------------      */
  403. /*           16 -> 00000000000000010000000000000000      */
  404. /*           17 -> 00000000000000100000000000000000      */
  405. /*           18 -> 00000000000001000000000000000000      */
  406. meny_sig = 1 << mp_meny->mp_SigBit;
  407. gadget_sig = 1 << mp_gadget->mp_SigBit;
  408. timer_sig = 1 << mp_timer->mp_SigBit;
  409.  
  410.  
  411. /* Wait until we receive a message at one of the ports: Zzz */
  412. received_sig = Wait( meny_sig | gadget_sig | timer_sig );
  413.  
  414.  
  415. /* Which port sent us the signal? */
  416. if(  received_sig & meny_sig )
  417.   printf( "The Menu port!" );
  418.  
  419. if(  received_sig & gadget_sig )
  420.   printf( "The Gadget port!" );
  421.  
  422. if(  received_sig & timer_sig )
  423.   printf( "The Timer port!" );
  424.  
  425.  
  426.  
  427. To put a task to sleep until a message arrives at the message
  428. port "msgp", write:
  429.  
  430.  
  431.  
  432.  
  433. 4.2.8  COLLECT MESSAGES
  434.  
  435. To collect a message use the function GetMsg(). It will remove
  436. the message from that port's message list, and return a pointer
  437. to the message. If it could not find any message it returns
  438. NULL. Before your program terminates it should try to collect
  439. all waiting messages.
  440.  
  441.   Synopsis: msg = GetMsg( msgp );
  442.  
  443.   msg:      (struct Message *) If GetMsg() could find a
  444.             message at the port it returns a pointer to the
  445.             message, and removes the message from the queue.
  446.             If no message was found, it returns NULL.
  447.  
  448.   msgp:     (struct MsgPort *) Pointer to the message port you
  449.             want to get the message from.
  450.  
  451.  
  452. For example: (It will try to collect a message, type MyMessage,
  453. from the port "msgp".)
  454.  
  455. /* Declare a pointer to the message we hopefully */
  456. /* will be able to collect: (MyMessage structure */
  457. /* is defined above.)                            */
  458. struct MyMessage *temp_msg;
  459.  
  460.   /* Try to collect a message: */
  461.   temp_msg = GetMsg( msgp );
  462.  
  463.   /* Collect some values: */
  464.   printf( "%s is %d years old!", temp_msg->namn, temp_msg->age );
  465.  
  466.  
  467.  
  468. 4.2.9  REPLY
  469.  
  470. When you have received a message, and examined and altered it
  471. as desired it is time to reply. When you reply will the other
  472. task be informed that you have finished using the message, and
  473. the other task may now do what it want with it. After you have
  474. replied you may not read or alter the message any more!
  475.  
  476. Use the function ReplyMsg() to reply to the sender. (ReplyMsg()
  477. will send the message to the reply port found in the messages
  478. "mn_ReplyPort field").
  479.  
  480.   Synopsis: ReplyMsg( msg );
  481.   
  482.   msg:      (struct Message *) Pointer to the message you have
  483.             previously collected, and do not want to use any
  484.             more.
  485.  
  486.  
  487. For example: (After we have used the message we received above,
  488. we reply as soon as possible.)
  489.  
  490.   ReplyMsg( temp_msg );
  491.  
  492.  
  493.  
  494. 4.3  EXAMPLE
  495.  
  496. Here is a complete example of two programs that will try to
  497. communicate with each other.
  498.  
  499.  
  500.  
  501. 4.3.1 PROGRAM A
  502.  
  503. /* This program will create a message port called "NrPort".   */
  504. /* It will then go to sleep and will first wake up when it    */
  505. /* has received a message. It will collect the message, read  */
  506. /* and alter it before it replies and the program terminates. */
  507.  
  508.  
  509. #include <exec/types.h>  /* STRPTR         */
  510. #include <exec/ports.h>  /* struct Message */
  511. #include <exec/memory.h> /* MEMF_PUBLIC    */
  512. #include <exec/nodes.h>  /* NT_MESSAGE     */
  513.  
  514.  
  515. /* Declare a pointer to our message port: */
  516. struct MsgPort *msgp;
  517.  
  518. /* The message will come in this form: */
  519. struct NrMessage
  520. {
  521.   struct Message SystemMsg;
  522.   int number;
  523. };
  524.  
  525. /* Declare a pointer to the message: */
  526. struct NrMessage *nrmsg;
  527.  
  528.  
  529. /* Declare the functions: */
  530. void clean_up();
  531. void main();
  532.  
  533.  
  534. void main()
  535. {
  536.   /* Create a message port: (Name "NrPort", priority 0) */
  537.   msgp = (struct MsgPort *) CreatePort( "NrPort", 0 );
  538.  
  539.   /* Check if we have successfully created a port: */ 
  540.   if( !msgp )
  541.     clean_up( "Could not create the message port!" );
  542.  
  543.  
  544.   /* Wait for a message to arrive: */
  545.   printf( "A: Waiting for a message to arrive...\n" );
  546.   WaitPort( msgp );
  547.  
  548.  
  549.   /* Now one or more messages have arrived, try to collect */
  550.   /* as many messages as possible:                         */
  551.   while( nrmsg = (struct NrMessage *) GetMsg( msgp ))
  552.   {
  553.     /* Read the message: */
  554.     printf( "A: The value we received was: %d\n", nrmsg->number );
  555.     printf( "A: Lets change it!\n" );
  556.  
  557.     /* Alter it: */
  558.     nrmsg->number = 67890;
  559.  
  560.     /* Reply: */
  561.     ReplyMsg( nrmsg );
  562.  
  563.     /* Note that after we have replied, we may not */
  564.     /* read or alter the message any more!         */
  565.   }
  566.  
  567.  
  568.   clean_up( "The End!" );
  569. }
  570.  
  571.  
  572. void clean_up( text )
  573. STRPTR text;
  574. {
  575.   /* If we have successfully created a port, close it: */ 
  576.   if( msgp )
  577.     DeletePort( msgp);
  578.  
  579.   /* Print any message: */
  580.   printf( "A: %s\n", text );
  581.  
  582.   /* Quit: */
  583.   exit( 0 );
  584. }
  585.  
  586.  
  587.  
  588. 4.3.2 PROGRAM B
  589.  
  590. /* This program will create a message of type NrMessage.    */
  591. /* It will then try to find a message port called "NrPort". */
  592. /* If it finds that port it will send a message to it, and  */
  593. /* wait for the other task to reply.                        */
  594.  
  595.  
  596. #include <exec/types.h>  /* STRPTR         */
  597. #include <exec/ports.h>  /* struct Message */
  598. #include <exec/memory.h> /* MEMF_PUBLIC    */
  599. #include <exec/nodes.h>  /* NT_MESSAGE     */
  600.  
  601.  
  602. /* Declare a pointer to our message and reply port: */
  603. struct MsgPort *msgp, *replymsgp;
  604.  
  605. /* The message will be in this form: */
  606. struct NrMessage
  607. {
  608.   struct Message SystemMsg;
  609.   int number;
  610. };
  611.  
  612. /* Declare a pointer to the message: */
  613. struct NrMessage *nrmsg;
  614.  
  615.  
  616. /* Declare the functions: */
  617. void clean_up();
  618. void main();
  619.  
  620.  
  621. void main()
  622. {
  623.   /* Allocate memory for the message: */
  624.   /* (Make it public and clear it.)   */
  625.   nrmsg = (struct NrMessage *)
  626.      AllocMem( sizeof( struct NrMessage ), MEMF_PUBLIC|MEMF_CLEAR );
  627.  
  628.   /* Check if we have allocated the memory successfully: */
  629.   if( !nrmsg )
  630.     clean_up( "Not enough memory for message!" );
  631.  
  632.  
  633.   /* Try to find the message port "NrPort": */
  634.   msgp = (struct MsgPort *) FindPort( "NrPort" );
  635.  
  636.   /* Have we found the message port? */
  637.   if( !msgp )
  638.     clean_up( "Could not find the message port!" );
  639.  
  640.  
  641.   /* Create a reply port: (When the other task replies */
  642.   /* we will receive a message at this port.)          */
  643.   replymsgp = (struct MsgPort *) CreatePort( "NrReplyPort", 0 );
  644.  
  645.   /* Have we received a reply port? */
  646.   if( !replymsgp )
  647.     clean_up( "Could not create the reply port!" );
  648.  
  649.  
  650.   /* Initialize the message: */
  651.   /* Set type to NT_MESSAGE: */
  652.   nrmsg->SystemMsg.mn_Node.ln_Type = NT_MESSAGE;
  653.  
  654.   /* Give the message a pointer to our reply port: */
  655.   nrmsg->SystemMsg.mn_ReplyPort = replymsgp;
  656.  
  657.   /* Set the length of our message: */
  658.   nrmsg->SystemMsg.mn_Length = sizeof( struct NrMessage );
  659.  
  660.   /* Set the message itself: */
  661.   nrmsg->number = 12345;
  662.  
  663.  
  664.   /* Inform the user: */
  665.   printf( "B: We have now successfully prepared everything!\n" );
  666.   printf( "B: Lets send the value: %d\n", nrmsg->number );
  667.  
  668.   /* Send the message: */  
  669.   PutMsg( msgp, nrmsg );
  670.  
  671.   /* After we have sent our message and until we */
  672.   /* receive a reply we are not allowed to read  */
  673.   /* or alter the message any more!              */
  674.   printf( "B: Message sent, lets wait...\n" );
  675.  
  676.  
  677.   /* Wait at our reply port: */
  678.   WaitPort( replymsgp );
  679.  
  680.  
  681.   /* Try to  receive as many messages as possible  */
  682.   /* from the reply port. (In this example we will */
  683.   /* only receive one reply, but you never know.)  */
  684.   while( GetMsg( replymsgp ))
  685.   {
  686.     /* We may now examine the message: */
  687.     printf( "B: We have received a reply!\n" );
  688.     printf( "B: The value is now: %d\n", nrmsg->number  );
  689.   }
  690.  
  691.  
  692.   /* The End! */
  693.   clean_up( "The End!" );
  694. }
  695.  
  696.  
  697. void clean_up( text )
  698. STRPTR text;
  699. {
  700.   /* If we have successfully allocated memory for a message */
  701.   /* deallocate it. (Note that we may not deallocate this   */
  702.   /* message if we have sent it to another task's message   */
  703.   /* port, and have not received any reply!)                */
  704.   if( nrmsg )
  705.     FreeMem( nrmsg, sizeof( *nrmsg ) );
  706.  
  707.   /* If we have we successfully created a reply */
  708.   /* port, close it:                            */
  709.   if( replymsgp )
  710.     DeletePort( replymsgp);
  711.  
  712.   /* Print any message: */
  713.   printf( "B: %s\n", text );
  714.  
  715.   /* Quit: */
  716.   exit( 0 );
  717. }
  718.  
  719.  
  720.  
  721. 4.4  FUNCTIONS
  722.  
  723. CreatePort()
  724.  
  725.   CreatePort() allocates and initializes a MsgPort structure.
  726.   If you give it a string as first parameter it will also make
  727.   the port public. (A port that has a name can be found by
  728.   other tasks and is therefore "public".) If CreatePort() of
  729.   some reason could not create a message port it returns NULL,
  730.   otherwise if everything is OK it returns a pointer to the
  731.   new MsgPort structure.
  732.  
  733.   Synopsis: msgp = CreatePort( name, pri );
  734.   
  735.   msgp:     (struct MsgPort *) Pointer to the new MsgPort
  736.             structure, or NULL if something went wrong.
  737.  
  738.   name:     (char *) Pointer to a string containing the name
  739.             of the message port, or NULL. If it is a string
  740.             the port will be made public (so other tasks can
  741.             find it) else only our task can use it.
  742.   
  743.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure
  744.             that should be allocated.
  745.  
  746.   pri:      (BYTE) This message port's priority. Usually set
  747.             to 0 - normal priority.
  748.  
  749.  
  750. DeletePort()
  751.  
  752.   DeletePort() will close a message port that is presently
  753.   open. All ports that has been created must be closed before
  754.   the program may terminate.
  755.  
  756.   Synopsis: DeletePort( msgp );
  757.  
  758.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure,
  759.             that should be closed.
  760.  
  761.  
  762. FindPort()
  763.  
  764.   FindPort() will try to locate an already existing message
  765.   port. If the function finds the port it returns a pointer to
  766.   it, else the function returns NULL.
  767.  
  768.   Synopsis: msgp = FindPort( name );
  769.   
  770.   msgp:     (struct MsgPort *) FindPort() will return a pointer
  771.             to the port we asked for, or NULL if it could not
  772.             find it.
  773.  
  774.   name:     (char *) Pointer to a string containing the name of
  775.             the port we are looking for.
  776.  
  777.  
  778. PutMsg()
  779.  
  780.   PutMsg() will put a message at the end of the port's queue
  781.   of messages. Note that after you have sent a message you may
  782.   not read or alter it until the other task has replied!
  783.  
  784.   Synopsis: PutMsg( msgp, message );
  785.  
  786.   msgp:     (struct MsgPort *) Pointer to the message port
  787.             to which you want to send a message.
  788.  
  789.   message:  (struct Message *) Pointer to the whole message
  790.             area.
  791.  
  792.  
  793. WaitPort()
  794.  
  795.   WaitPort() will put the task to sleep, and will first wake
  796.   up when a message arrives. While the task is sleeping it does
  797.   not use any computer time.
  798.  
  799.   Synopsis: msg = WaitPort( msgp );
  800.   
  801.   msg:      (struct Message *) When a message arrives the task
  802.             is woken up and WaitPort() returns a pointer to the
  803.             first message that has arrived. (There may arrive
  804.             several messages at the same time.)
  805.  
  806.   msgp:     (struct MsgPort *) Pointer to the message port you
  807.             want to wait at.
  808.  
  809.  
  810. Wait()
  811.  
  812.   Wait() will put the task to sleep, and will first wake up
  813.   when one of the specified signal bits arrives. The advantage
  814.   with this function compared to WaitPort() is that you can
  815.   monitor several message ports at the same time. You only
  816.   need to tell Wait() which signal you want to wait for, and
  817.   once one or more of them arrives the task is put to work
  818.   again.
  819.  
  820.   Synopsis: rsig = Wait( wsig )
  821.  
  822.   rsig:     (ULONG) When one of the specified signal bits was
  823.             received, the task is woken up and Wait() returns
  824.             the signal bit value that woke it up.
  825.  
  826.   wsig:     (ULONG) Wait() will put the task to sleep, and it
  827.             will only wake up if one of the specified signal
  828.             bit values is received.
  829.  
  830.  
  831. GetMsg()
  832.  
  833.   GetMsg() will try to remove a message from the port's
  834.   message list, and return a pointer to the message. If it
  835.   could not find any message it returns NULL. Before your
  836.   program terminates it should try to collect all waiting
  837.   messages.
  838.  
  839.   Synopsis: msg = GetMsg( msgp );
  840.  
  841.   msg:      (struct Message *) If GetMsg() could find a
  842.             message at the port it returns a pointer to the
  843.             message, and removes the message from the queue.
  844.             If no message was found, it returns NULL.
  845.  
  846.   msgp:     (struct MsgPort *) Pointer to the message port you
  847.             want to get the message from.
  848.  
  849.  
  850. ReplyMsg()
  851.  
  852.   ReplyMsg() replies to the sender. All messages you have
  853.   collected should be replied. Note that after you have replied
  854.   you may not use the message any more!
  855.  
  856.   Synopsis: ReplyMsg( msg );
  857.   
  858.   msg:      (struct Message *) Pointer to the message you have
  859.             previously collected, and do not want to use any
  860.             more.
  861.  
  862.  
  863.  
  864. 4.5  EXAMPLES
  865.  
  866. Example 1
  867.   A: This program will create a message port called "NrPort".
  868.   It will then go to sleep and will first wake up when it has
  869.   received a message. It will collect the message, read and
  870.   alter it before it replies and the program terminates.
  871.  
  872.   B: This program will create a message of type NrMessage. It
  873.   will then try to find a message port called "NrPort". If it
  874.   finds that port it will send a message to it, and wait for
  875.   the other task to reply.
  876.  
  877.   Start program A then program B.
  878.  
  879.  
  880. Example 2
  881.   This program will open the Timer Device to which we  connect
  882.   a message port. When the Timer Device has done our request
  883.   (waiting for 10 seconds) it will send a message to the
  884.   message port which tells us that the time has passed.
  885.  
  886.   This example demonstrates how you can give the system (like
  887.   the Timer Device) a message port through which the system can
  888.   communicate with us. Although we are using the Timer Device,
  889.   it is only as a demonstration on how to work with message
  890.   ports. For more information about the Timer Device, see
  891.   chapter Timer Device.
  892.  
  893.  
  894. Example 3
  895.   This program will open two ports. The first port is used by
  896.     the Timer Device while the second port will not be used at
  897.     all (it is a dummy port). The reason why this example opens
  898.     an extra port is because I want to demonstrate how you can
  899.     handle two message ports simultaniously. With this technique
  900.     you can monitor up to 32 ports (the system usually needs some
  901.     singnals, but you have at least 16 signals for yourself).
  902.  
  903.  
  904.